package com.qf.smartplatform.service.Impl;/*
*王浩政
*whz
2022/9/7
22:04
*小米商城
*/

import com.qf.smartplatform.constans.ResultCode;
import com.qf.smartplatform.dto.UserDto;
import com.qf.smartplatform.event.LoginFailEvent;
import com.qf.smartplatform.exceptions.AddDataException;
import com.qf.smartplatform.exceptions.FindDataException;
import com.qf.smartplatform.event.LoginSuccessEvent;
import com.qf.smartplatform.mapper.UserMapper;
import com.qf.smartplatform.pojo.SysUserInfo;
import com.qf.smartplatform.service.UserService;
import com.qf.smartplatform.utils.MyStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.util.List;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    private ApplicationContext context;

    @Autowired
    public void setContext(ApplicationContext context){
        this.context=context;
    }
private UserMapper userMapper;

    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public void addUser(UserDto userDto){
//        Assert.isTrue(!userDto.isEmpty(),()->{
//            throw new AddDataException("参数为空", ResultCode.PARAM_CONTENT_EMPTY);
//        });
        //需要查询一下数据是不是存在，存在需要提请一下客户端，账号已经存在
        List<SysUserInfo> userInfoList =
                userMapper.findByUserNameOrPhoneOrEmail(userDto.getUsername(), userDto.getPhone(), userDto.getEmail());
//        if (userInfoList.size()>0) {
//
//        }
        Assert.isTrue(userInfoList.size()==0,()->{
            throw new AddDataException("账号有过啦！", ResultCode.USERNAME_ALREADY_EXIST);
           // throw new AddDataException("账号有过啦！",ResultCode.USERNAME_ALREADY_EXIST);
        });
        //手机号的格式，邮箱的格式


        //对数据进行校验，转换到SysUserInfo上面
        SysUserInfo sysUserInfo = new SysUserInfo();
        //拷贝数据，就是要求属性名一样
        //sysUserInfo.setUsername(userDto.getUsername());
        BeanUtils.copyProperties(userDto,sysUserInfo);
        //将密码转成散列值，比如MD5值
        //MD5值是相同的内容总是会有相同的MD5值，所以未了避免相同的密码在数据库中显示相同的内容，我们会对数据进行加盐
        //盐不能一样，因为盐如果一样那就是一样的密码了，没有区别了，盐是我们随机生成的
        //我们随机生成一个十位的字符串
        String salt = MyStringUtils.creatRandomString(10);
        //我们的盐需要保存，不然输入后怎么后续确认呢？
        sysUserInfo.setPwdSalt(salt);
        //我们真正的密码是salt+password+salt
        String passwordMD5 = DigestUtils.md5DigestAsHex((salt + sysUserInfo.getPassword() + salt).getBytes(StandardCharsets.UTF_8));
        //将密码替换成MD5值
        sysUserInfo.setPassword(passwordMD5);
        //自己注册的就是自己
        sysUserInfo.setCreateBy(sysUserInfo.getUsername());
        sysUserInfo.setRemark("普通用户名");
        userMapper.addUser(sysUserInfo);
    }

    @Override
    public SysUserInfo findUserByName(String userName){
        //必须传递用户名
//        Assert.hasText(userName,()->{
//            throw new FindDataException("用户名不能为空",ResultCode.PARAM_CONTENT_EMPTY);
//        });
        SysUserInfo user=userMapper.findUserByName(userName);
        return user;
    }

    @Override
    public SysUserInfo login(String userName, String password) {
        SysUserInfo sysUserInfo=findUserByName(userName);
        //将用户传递过来的密码和盐一起计算出来了一个MD值，如果这个和查询的结果是一样的，那么就代表这查询成功
        String passwordMD5 = DigestUtils.md5DigestAsHex((sysUserInfo.getPwdSalt() + password + sysUserInfo.getPwdSalt()).getBytes(StandardCharsets.UTF_8));
        Assert.isTrue(passwordMD5.equals(sysUserInfo.getPassword()),()->{
            context.publishEvent(new LoginFailEvent(null,userName));
            throw new FindDataException("用户名密码错误",ResultCode.USERNAME_PASSWORD_ERROR);
        });
        //更新日志不是当前业务的核心操作，属于辅助操作，并且成功与否不能影响前面的登陆操作，所以当前操作可以放在异步中执行
        //那要怎么样才能搞一个异步过来呢？
        //虽然我们的需求中并没有展示登录时间等操作，但是要记住，我们几乎所有和登录，修改等的操作，在表中都有对应的时间列
        //我们需要更新用户的数据，登录在的时间和ip

        //String ip = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getRemoteHost();
        //userMapper.updateLoginDataByUserId(sysUserInfo.getUId(),ip);
        context.publishEvent(new LoginSuccessEvent(sysUserInfo.getUId(),sysUserInfo.getUsername()));
        return sysUserInfo;
    }

    @Override
    public void updateLoginData(Long uid, String ip) {
        userMapper.updateLoginDataByUserId(uid,ip);
    }
}
